package com.gfilechooser.utils;

import java.io.File;
import java.io.FileFilter;
import java.net.URISyntaxException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.XmlResourceParser;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.provider.MediaStore;
import android.provider.MediaStore.Audio;
import android.provider.MediaStore.Video;
import android.util.Log;

import com.gfilechooser.R;

/**
 * @author Guillermo
 */

public class FileUtils {
	/** TAG for log */
	static final String TAG = FileUtils.class.getSimpleName();
	public static final String MIME_TYPE_AUDIO = "audio/*";
	public static final String MIME_TYPE_TEXT = "text/*";
	public static final String MIME_TYPE_IMAGE = "image/*";
	public static final String MIME_TYPE_VIDEO = "video/*";
	public static final String MIME_TYPE_APP = "application/*";

	public static boolean isLocal(String uri) {
		if (uri != null && !uri.startsWith("http://")) {
			return true;
		}
		return false;
	}

	public static String getExtension(String uri) {
		String methodName = "getExtension()";
		Log.d(TAG, methodName);
		if (uri == null) {
			return null;
		}

		int dot = uri.lastIndexOf(".");
		if (dot >= 0) {
			return uri.substring(dot);
		} else {
			Log.i(TAG, methodName + " no extension found");
			return "";
		}
	}

	public static boolean isMediaUri(Uri uri) {
		String uriString = uri.toString();
		if (uriString.startsWith(Audio.Media.INTERNAL_CONTENT_URI.toString())
				|| uriString.startsWith(Audio.Media.EXTERNAL_CONTENT_URI
						.toString())
				|| uriString.startsWith(Video.Media.INTERNAL_CONTENT_URI
						.toString())
				|| uriString.startsWith(Video.Media.EXTERNAL_CONTENT_URI
						.toString())) {
			return true;
		} else {
			return false;
		}
	}

	public static Uri getUri(File file) {
		if (file != null) {
			return Uri.fromFile(file);
		}
		return null;
	}

	public static File getFile(Uri uri) {
		if (uri != null) {
			String filepath = uri.getPath();
			if (filepath != null) {
				return new File(filepath);
			}
		}
		return null;
	}

	public static File getPathWithoutFilename(File file) {
		if (file != null) {
			if (file.isDirectory()) {
				return file;
			} else {
				String filename = file.getName();
				String filepath = file.getAbsolutePath();
				String pathwithoutname = filepath.substring(0,
						filepath.length() - filename.length());
				if (pathwithoutname.endsWith("/")) {
					pathwithoutname = pathwithoutname.substring(0,
							pathwithoutname.length() - 1);
				}
				return new File(pathwithoutname);
			}
		}
		return null;
	}

	public static File getFile(String curdir, String file) {
		String separator = "/";
		if (curdir.endsWith("/")) {
			separator = "";
		}
		File clickedFile = new File(curdir + separator + file);
		return clickedFile;
	}

	public static File getFile(File curdir, String file) {
		return getFile(curdir.getAbsolutePath(), file);
	}

	public static String getPath(Context context, Uri uri)
			throws URISyntaxException {
		String methodName = "getPath()";
		final String content = "content";
		final String _data = "_data";
		final String file = "file";
		Log.d(TAG + methodName + " File -",
				"Authority: " + uri.getAuthority() + ", Fragment: "
						+ uri.getFragment() + ", Port: " + uri.getPort()
						+ ", Query: " + uri.getQuery() + ", Scheme: "
						+ uri.getScheme() + ", Host: " + uri.getHost()
						+ ", Segments: " + uri.getPathSegments().toString());

		if (content.equalsIgnoreCase(uri.getScheme())) {
			String[] projection = { _data };
			Cursor cursor = null;

			try {
				cursor = context.getContentResolver().query(uri, projection,
						null, null, null);
				int column_index = cursor.getColumnIndexOrThrow(_data);
				if (cursor.moveToFirst()) {
					return cursor.getString(column_index);
				}
			} catch (Exception e) {
				Log.i(TAG, methodName + " error doesn't care");
			}
		} else if (file.equalsIgnoreCase(uri.getScheme())) {
			return uri.getPath();
		}

		return null;
	}

	public static String getReadableFileSize(int size) {
		final int BYTES_IN_KILOBYTES = 1024;
		final DecimalFormat dec = new DecimalFormat("###.#");
		final String KILOBYTES = " KB";
		final String MEGABYTES = " MB";
		final String GIGABYTES = " GB";
		float fileSize = 0;
		String suffix = KILOBYTES;

		if (size > BYTES_IN_KILOBYTES) {
			fileSize = size / BYTES_IN_KILOBYTES;
			if (fileSize > BYTES_IN_KILOBYTES) {
				fileSize = fileSize / BYTES_IN_KILOBYTES;
				if (fileSize > BYTES_IN_KILOBYTES) {
					fileSize = fileSize / BYTES_IN_KILOBYTES;
					suffix = GIGABYTES;
				} else {
					suffix = MEGABYTES;
				}
			}
		}
		return String.valueOf(dec.format(fileSize) + suffix);
	}

	private static MimeTypes getMimeTypes(Context context) {
		String methodName = "getMimeTypes()";
		MimeTypes mimeTypes = null;
		final MimeTypeParser mtp = new MimeTypeParser();
		final XmlResourceParser in = context.getResources().getXml(
				R.xml.mimetypes);

		try {
			mimeTypes = mtp.fromXmlResource(in);
		} catch (Exception e) {
			Log.e(TAG, methodName, e);
		}
		return mimeTypes;
	}

	public static String getMimeType(Context context, File file) {
		String mimeType = null;
		final MimeTypes mimeTypes = getMimeTypes(context);
		if (file != null)
			mimeType = mimeTypes.getMimeType(file.getName());
		return mimeType;
	}

	public static Bitmap getThumbnail(Context context, File file) {
		return getThumbnail(context, getUri(file), getMimeType(context, file));
	}

	public static Bitmap getThumbnail(Context context, Uri uri) {
		return getThumbnail(context, uri, getMimeType(context, getFile(uri)));
	}

	public static Bitmap getThumbnail(Context context, Uri uri, String mimeType) {
		String methodName = "getThumbnail()";
		Log.d(TAG, methodName);
		if (isMediaUri(uri)) {
			Log.e(TAG,
					methodName
							+ " You can only retrieve thumbnails for images and videos.");
			return null;
		}
		Bitmap bm = null;
		if (uri != null) {
			final ContentResolver resolver = context.getContentResolver();
			Cursor cursor = null;
			try {
				cursor = resolver.query(uri, null, null, null, null);
				if (cursor.moveToFirst()) {
					final int id = cursor.getInt(0);
					Log.d(TAG, methodName + " Got thumb ID: " + id);
					if (mimeType.contains("video")) {
						bm = MediaStore.Video.Thumbnails
								.getThumbnail(resolver, id,
										MediaStore.Video.Thumbnails.MINI_KIND,
										null);
					} else if (mimeType.contains(FileUtils.MIME_TYPE_IMAGE)) {
						bm = MediaStore.Images.Thumbnails.getThumbnail(
								resolver, id,
								MediaStore.Images.Thumbnails.MINI_KIND, null);
					}
				}
			} catch (Exception e) {
				Log.e(TAG, methodName, e);
			} finally {
				if (cursor != null)
					cursor.close();
			}
		}
		return bm;
	}

	private static final String HIDDEN_PREFIX = ".";

	private static Comparator<File> comparator = new Comparator<File>() {
		public int compare(File f1, File f2) {
			return f1.getName().toLowerCase()
					.compareTo(f2.getName().toLowerCase());
		}
	};

	private static FileFilter fileFilter = new FileFilter() {
		public boolean accept(File file) {
			final String fileName = file.getName();
			return file.isFile() && !fileName.startsWith(HIDDEN_PREFIX);
		}
	};

	private static FileFilter dirFilter = new FileFilter() {
		public boolean accept(File file) {
			final String fileName = file.getName();
			return file.isDirectory() && !fileName.startsWith(HIDDEN_PREFIX);
		}
	};

	public static List<File> getFileList(String path) {
		ArrayList<File> list = new ArrayList<File>();
		final File pathDir = new File(path);
		final File[] dirs = pathDir.listFiles(dirFilter);
		if (dirs != null) {
			Arrays.sort(dirs, comparator);
			for (File dir : dirs)
				list.add(dir);
		}
		final File[] files = pathDir.listFiles(fileFilter);
		if (files != null) {
			Arrays.sort(files, comparator);
			for (File file : files)
				list.add(file);
		}

		return list;
	}

	public static Intent createGetContentIntent() {
		String methodName = "createGetContentIntent()";
		Log.i(TAG, methodName);
		final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
		intent.setType("*/*");
		intent.addCategory(Intent.CATEGORY_OPENABLE);
		return intent;
	}
}
